package jp.kentaro.plugin.lwjgl.samples.test4.views;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.nio.*;

import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.lwjgl.*;
import org.lwjgl.opengl.*;

public class TextureLoader{

	public static ImageData createImageData(int width, int height) {
		// Create Color Palette
		PaletteData palette = new PaletteData(new RGB[] {
				new RGB(0xFF, 0x00, 0x00),
				new RGB(0x00, 0xFF, 0x00),
				new RGB(0x00, 0x00, 0xFF)
		});
		
		// Create ImageData Object
		ImageData imageData = new ImageData(width, height, 32, palette);
		
		// Write a pixcel to ImageData Object
		for (short h=0 ; h < height ; h++) {
			for (short w=0 ; w < width ; w++) {
				int pixelValue = (h/20 + w/20) % 3;
				imageData.setPixel(h, w, pixelValue);
			}
		}
		
		return imageData;
	}
	
	public InputStream getInputStream(String resource) {
		
		InputStream stream = this.getClass().getResourceAsStream(resource);
		
		if (stream == null)  stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
		
		if (stream == null) {
			File file = new File(resource);
			try {
				return new FileInputStream(file);
			} catch (Exception ex) {
				//
			}
			
			try {
				URL sourceUrl = new URL(resource);
				if (sourceUrl != null) {
					stream = sourceUrl.openStream();
				}
			} catch (Exception e) {
				return null;
			}
		}
		return stream;
	}
	
	public Texture loadTexture(String name, boolean flip) {
		Texture    texture = null;
		ByteBuffer imageData = null;
		boolean    haveToResize = false;
		
		// get source image data
		ImageData src = new ImageData(getInputStream(name));
		//ImageData src = createImageData(256,256);
		
		// get image attributes
		int width = src.width;
		int height = src.height;
		int textureWidthSize = getNextPowerOfTwo(width);
		int textureHeightSize = getNextPowerOfTwo(height);
		
		if (textureWidthSize != width || textureHeightSize != height) {
			haveToResize = true;
		}
		// convert image to RGBA
		//int step = src.depth / 8;
		
		int step = 4;
		byte[] data = new byte[src.width * src.height * 4];
		
		for(int y = 0; y < src.height; y++) {
			int offset = 4* y * src.width;
			for(int x =0; x < src.width ; x++) {
				int index = x * 3 + y * src.bytesPerLine;
				int offset_x = x *step;
				data[offset + offset_x + 0] = src.data[index + 2];
				data[offset + offset_x + 1] = src.data[index + 1];
				data[offset + offset_x + 2] = src.data[index + 0];
				data[offset + offset_x + 3] = 0;
			}
		}
		
		//byte[]     data     = new byte[src.data.length];
		//for(int i=0; i<src.data.length; i++) 
		//	data[i] = src.data[src.data.length-(i+0x1)];
		
		//ByteBuffer imageData  = ByteBuffer.wrap(data);
		
		// resize image according to poweroftwo
		//if (textureWidthSize != width || textureHeightSize != height) {
		//	imageData = (ByteBuffer)BufferUtils.createByteBuffer(textureWidthSize * textureHeightSize * 4).put(data, 0x0, data.length).flip();
		//} else {
			imageData = (ByteBuffer)BufferUtils.createByteBuffer(data.length).put(data, 0x0, data.length).flip();
		//}
		
		IntBuffer  buffer   = ByteBuffer.allocateDirect(0x4).order(ByteOrder.nativeOrder()).asIntBuffer();
		
		// create OpenGL counterpart
		GL11.glGenTextures(buffer);
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, buffer.get(0));
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
		GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 
			0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, imageData);
		
		// Create image (either resized by copying, else directly from IL)
		//if (textureWidthSize != width || textureHeightSize != height) {
		//	texture = new Texture(buffer.get(0), width, height, (width / (float) textureWidthSize),
		//						(height / (float) textureHeightSize), textureWidthSize, textureHeightSize);
		//} else {
			texture = new Texture(buffer.get(0x0), width, height);
		//}
		
		return texture;
	}
		
	public static int getNextPowerOfTwo(int fold) {
		int pow = 2;
		while (pow < fold) {
			pow *= 2;
		}
		return pow;
	}
}